
package uk.ac.cam.cl.oscar;

import java.io.*;
import java.awt.image.BufferedImage;
import java.lang.*;
import java.sql.Blob;

/** Equivalent to KeypointPacker. See its methods for how to use */
public class BufferedImagePacker {

	public static int usByteToInt (byte b)
	{
		return (int)b & 0xFF;
	}

	private static int DWordToInt (byte bh, byte bl) {
		return usByteToInt(bh) << 8 | usByteToInt (bl);
	}

	private static byte[] intToDWord(int i) {
		byte[] dword = new byte[2];
		dword[0] = (byte) ((i >>> 8)  & 0xFF);
		dword[1] = (byte) (i & 0xFF);
		return dword;
	}

	/* Only stores RGB. alpha disgarded */
	public static byte[] toByteArray (BufferedImage image) 
	{
		int[] pixels = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());
		
		int headerSize = 4;
		byte[] buf = new byte[headerSize + pixels.length * 3];
		
		byte[] dword = intToDWord (image.getWidth());
		buf[0] = dword[0];
		buf[1] = dword[1];
		
		dword = intToDWord (image.getHeight());
		buf[2] = dword[0];
		buf[3] = dword[1];
		
		for (int i = 0; i < pixels.length; i++) {
			buf[headerSize + 3*i] = (byte) (pixels[i] & 0xFF);
			buf[headerSize + 3*i+1] = (byte) ((pixels[i] >>> 8) & 0xFF);
			buf[headerSize + 3*i+2] = (byte) ((pixels[i] >>> 16) & 0xFF);
		}
		
		return buf;
	}
	
	
	/* Alpha assumed 0xFF */
	public static BufferedImage fromBlob (Blob blob) throws IOException
	{
		
		byte[] buffer = null;
		try {
			buffer = blob.getBytes ((long)1, (int)blob.length());
		} catch (java.sql.SQLException e) {
			System.out.println ("Could not read contents of Image Blob");
			return null;
		}
		
		int headerSize = 4;
		
		if (buffer.length > headerSize) {
			int width = DWordToInt (buffer[0], buffer[1]);
			int height = DWordToInt (buffer[2], buffer[3]);
			
			BufferedImage image = new BufferedImage (width, height, 	
				BufferedImage.TYPE_INT_RGB);
			
			int count = 0;
			while (count < width*height) {
				image.setRGB (count % width, count / width, 
					usByteToInt(buffer[headerSize + count*3]) | 
					usByteToInt(buffer[headerSize + count*3 + 1]) <<8 | 
					usByteToInt(buffer[headerSize + count*3 + 2]) << 16);
				count++;
			}
			
			return image;
		}
		else {
			throw new IOException ("Couldn't read header off of image byte stream");
		}
	}
	
}